---
title: Subscriptions
description: Persistent GraphQL read operations
---

import {ExpansionPanel} from 'gatsby-theme-apollo-docs';

> **Subscriptions are not currently supported in [Apollo Federation](https://www.apollographql.com/docs/federation/).**

**Subscriptions** are long-lasting GraphQL read operations that can update their result whenever a particular server-side event occurs. Most commonly, updated results are _pushed_ from the server to subscribing clients. For example, a chat application's server might use a subscription to push newly received messages to all clients in a particular chat room.

Because subscription updates are usually pushed by the server (instead of polled by the client), they usually use [the WebSocket protocol](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API) instead of HTTP. To support this, Apollo Server lets you [set a subscription-specific endpoint](#setting-a-subscription-endpoint) that's separate from the default endpoint for queries and mutations.

You can use subscriptions with the core `apollo-server` library, or with any of Apollo Server's supported [middleware integrations](#using-with-middleware-integrations).

> **Important:** Compared to queries and mutations, subscriptions are significantly more complex to implement. Before you begin, [confirm that your use case requires subscriptions](https://www.apollographql.com/docs/react/data/subscriptions/#when-to-use-subscriptions).

## Schema definition

Your schema's `Subscription` type defines top-level fields that clients can subscribe to:

```graphql
type Subscription {
  postCreated: Post
}
```

The `postCreated` field will update its value whenever a new `Post` is created on the backend, thus pushing the `Post` to subscribing clients.

Clients can subscribe to the `postCreated` field with a GraphQL string like this:

```graphql
subscription PostFeed {
  postCreated {
    author
    comment
  }
}
```

> Each subscription operation can subscribe to only _one_ field of the `Subscription` type.

## Setting a subscription endpoint

Because subscriptions use WebSocket instead of HTTP, Apollo Server uses a _second_ GraphQL endpoint specifically for subscriptions. This endpoint uses the `ws` protocol instead of `http`.

By default, the subscription endpoint's path matches the path of your primary GraphQL endpoint (`/graphql` if not set). You can specify a different path for your subscription endpoint like so:

```js
const server = new ApolloServer({
  subscriptions: {
    path: '/subscriptions'
  },
  // ...other options...
}));
```

## Resolving a subscription

Resolvers for `Subscription` fields differ from resolvers for fields of other types. Specifically, `Subscription` field resolvers are _objects_ that define a `subscribe` function:

```js:title=index.js
const resolvers = {
  Subscription: {
    postCreated: {
      // More on pubsub below
      subscribe: () => pubsub.asyncIterator(['POST_CREATED']),
    },
  },
  // ...other resolvers...
};
```

The `subscribe` function must return an object of type `AsyncIterator`, a standard interface for iterating over asynchronous results. In the example above, an `AsyncIterator` is generated by `pubsub.asyncIterator` (more on this below).


### The `PubSub` class

> The `PubSub` class is **not** recommended for production environments, because it's an in-memory event system that only supports a single server instance. After you get subscriptions working in development, we strongly recommend switching it out for a different subclass of the abstract [`PubSubEngine` class](https://github.com/apollographql/graphql-subscriptions/blob/master/src/pubsub-engine.ts). Recommended subclasses are listed in [Production `PubSub` libraries](#production-pubsub-libraries).

Apollo Server uses a **publish-subscribe** (**pub/sub**) model to track events that update active subscriptions. The [`graphql-subscriptions` library](https://github.com/apollographql/graphql-subscriptions) (included in every `apollo-server` package) provides the `PubSub` class as a basic in-memory event bus to help you get started:

```js
const { PubSub } = require('apollo-server');

const pubsub = new PubSub();
```

A `PubSub` instance enables your server code to both `publish` events to a particular label and listen for events associated with a particular label.

### Publishing an event

You publish an event with the `publish` method of a `PubSub` instance:

```js
pubsub.publish('POST_CREATED', {
  postCreated: {
    author: 'Ali Baba',
    comment: 'Open sesame'
  }
});
```

* The first parameter is the name of the event label you're publishing to, as a string.
    * _You don't need to register a label name before publishing to it._
* The second parameter is the payload associated with the event.
    * _The payload should include whatever data is necessary for your resolvers to populate the associated `Subscription` field and its subfields._

When working with GraphQL subscriptions, you `publish` an event whenever a subscription's return value should be updated. One common cause of such an update is a mutation, but _any_ back-end logic might result in changes that should be `publish`ed.

As an example, let's say our GraphQL API supports a `createPost` mutation:

```graphql
type Mutation {
  createPost(author: String, comment: String): Post
}
```

A basic resolver for `createPost` might look like this:

```js{3-6}
const resolvers = {
  Mutation: {
    createPost(parent, args, context) {
      // Datastore logic lives in postController
      return postController.createPost(args);
    },
  },
  // ...other resolvers...
};
```

Before we persist the new post's details in our datastore, we can `publish` an event that _also_ includes those details:

```js
const resolvers = {
  Mutation: {
    createPost(parent, args, context) {
      pubsub.publish('POST_CREATED', { postCreated: args }); // highlight-line
      return postController.createPost(args);
    },
  },
  // ...other resolvers...
};
```

Next, we can listen for this event in our `Subscription` field's resolver.

### Listening for events

An [`AsyncIterator`](https://github.com/apollographql/graphql-subscriptions/blob/master/src/pubsub-async-iterator.ts) object listens for events that are associated with a particular label (or set of labels) and adds them to a queue for processing. You create an `AsyncIterator` by calling the `asyncIterator` method of `PubSub`:

```js
pubsub.asyncIterator(['POST_CREATED']);
```

You pass this method an array containing the names of all event labels that the `AsyncIterator` should listen for.

Every `Subscription` field resolver's `subscribe` function must return an `AsyncIterator` object. This brings us back to the code sample at the top of [Resolving a subscription](#resolving-a-subscription):

```js:title=index.js
const resolvers = {
  Subscription: {
    postCreated: {
      subscribe: () => pubsub.asyncIterator(['POST_CREATED']),
    },
  },
  // ...other resolvers...
};
```

With this `subscribe` function set, Apollo Server uses the payloads of `POST_CREATED` events to push updated values for the `postCreated` field.

### Filtering events

Sometimes, a client should only receive updated subscription data if that data meets certain criteria. To support this, you can call the `withFilter` helper function in your `Subscription` field's resolver.

#### Example

Let's say our server provides a `commentAdded` subscription, which should notify clients whenever a comment is added to a specified code repository. A client can execute a subscription that looks like this:

```graphql
subscription($repoName: String!){
  commentAdded(repoFullName: $repoName) {
    id
    content
  }
}
```

This presents a potential issue: our server probably [publishes](#publishing-an-event)  a `COMMENT_ADDED` event whenever a comment is added to _any_ repository. This means that the `commentAdded` resolver executes for _every_ new comment, regardless of which repository it's added to. As a result, subscribing clients might receive data they don't want (or shouldn't even have access to).

To fix this, we can use the `withFilter` helper function to control updates on a per-client basis.

Here's an example resolver for `commentAdded` that uses the `withFilter` function:

```js{5-12}
const { withFilter } = require('apollo-server');

const resolvers = {
  Subscription: {
    commentAdded: {
      subscribe: withFilter(
        () => pubsub.asyncIterator('COMMENT_ADDED'),
        (payload, variables) => {
          // Only push an update if the comment is on
          // the correct repository for this operation
          return (payload.commentAdded.repository_name === variables.repoFullName);
        },
      ),
    }
  },
    // ...other resolvers...
};
```

The `withFilter` function takes two parameters:

* The first parameter is exactly the function you would use for `subscribe` if you _weren't_ applying a filter.
* The second parameter is a **filter function** that returns `true` if a subscription update _should_ be sent to a particular client, and `false` otherwise (`Promise<boolean>` is also allowed). This function takes two parameters of its own:
    * `payload` is the payload of the event that was published.
    * `variables` is an object containing all arguments the client provided when initiating their subscription.

Use `withFilter` to make sure clients get exactly the subscription updates they want (and are allowed to receive).


## Basic runnable example

An example server is available on [GitHub](https://github.com/apollographql/docs-examples/blob/main/server-subscriptions/index.js) and CodeSandbox:

<a href="https://codesandbox.io/s/github/apollographql/docs-examples/tree/main/server-subscriptions?fontsize=14&hidenavigation=1&theme=dark">
  <img alt="Edit server-subscriptions" src="https://codesandbox.io/static/img/play-codesandbox.svg"></img>
</a>


The server exposes one subscription (`numberIncremented`) that returns an integer that's incremented on the server every second. The example requires only the `apollo-server` library.

After you start up this server, you can test out running a subscription with the Apollo Studio Explorer or GraphQL Playground, as described in the [full-stack tutorial](https://www.apollographql.com/docs/tutorial/schema/#explore-your-schema). You'll see the subscription's value update every second.

> In the Apollo Studio Explorer, you must specify your server's subscription endpoint (`ws://localhost:4000/subscriptions`) in the **Explorer Settings** tab.

## Operation context

When [initializing context](../data/resolvers/#the-context-argument) for a query or mutation, you usually extract HTTP headers and other request metadata from the `req` object provided to the `context` function.

**For subscriptions,** you extract this metadata from the `connection` object instead. This object adheres to the [`ExecutionParams` interface](https://github.com/apollographql/subscriptions-transport-ws/blob/817e7de3a23db2b4d64eb846724175dba74025d0/src/server.ts#L24-L33).

Because all operation types use the same `context` initialization function, you should check which of `req` or `connection` is present for each incoming request:

```js
const server = new ApolloServer({
  context: ({ req, connection }) => {
    if (connection) { // Operation is a Subscription
      // Obtain connectionParams-provided token from connection.context
      const token = connection.context.authorization || "";
      return { token };
    } else { // Operation is a Query/Mutation
      // Obtain header-provided token from req.headers
      const token = req.headers.authorization || "";
      return { token };
    }
  },
});
```

This is especially important because metadata like auth tokens are sent differently depending on the transport.

## `onConnect` and `onDisconnect`

You can define functions that Apollo Server executes whenever a subscription request connects (`onConnect`) or disconnects (`onDisconnect`).

Defining an `onConnect` function provides the following benefits:

* You can reject a particular incoming connection by throwing an exception or returning `false` in `onConnect`.
  * This is especially useful for [authentication](#example-authentication-with-onconnect).
* If `onConnect` returns an object, that object's fields are added to the WebSocket connection's `context` object.
  * This is _not_ the _operation_ `context` that's passed between resolvers. However, you can transfer these values from the `connection`'s `context` when you [initialize operation context](#operation-context).

You provide these function definitions to the constructor of `ApolloServer`, like so:

```js
const server = new ApolloServer({
  subscriptions: {
    onConnect: (connectionParams, webSocket, context) => {
      console.log('Connected!')
    },
    onDisconnect: (webSocket, context) => {
      console.log('Disconnected!')
    },
    // ...other options...
  },
});
```

These functions are passed the following parameters:

<table class="field-table">
  <thead>
    <tr>
      <th>Name /<br/>Type</th>
      <th>Description</th>
    </tr>
  </thead>

<tbody>
<tr>
<td>

###### `connectionParams`

`Object`

</td>
<td>

**Passed to `onConnect` only.**

An object containing parameters included in the request, such as an [authentication token](#example-authentication-with-onconnect).

For details, see [Authenticate over WebSocket](https://www.apollographql.com/docs/react/data/subscriptions/#4-authenticate-over-websocket-optional) in the Apollo Client documentation.

</td>
</tr>

<tr>
<td>

###### `webSocket`

`WebSocket`
</td>
<td>

The connecting or disconnecting [`WebSocket`](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket).

</td>
</tr>

<tr>
<td>

###### `context`

`ConnectionContext`
</td>
<td>

Context object for the WebSocket connection. This is _not_ the `context` object for the associated subscription operation.

[See fields](https://github.com/apollographql/subscriptions-transport-ws/blob/master/src/server.ts#L35-L43)

</td>
</tr>

</tbody>
</table>

### Example: Authentication with `onConnect`

On the client, `SubscriptionsClient` supports adding token information to `connectionParams` ([example](https://www.apollographql.com/docs/react/advanced/subscriptions/#authentication-over-websocket)) that will be sent with the first WebSocket message. In the server, all GraphQL subscriptions are delayed until the connection has been fully authenticated and the `onConnect` callback returns a truthy value.

The `connectionParams` argument in the `onConnect` callback contains the information passed by the client and can be used to validate user credentials.
The GraphQL context can also be extended with the authenticated user data to enable fine grain authorization.

```js
const { ApolloServer } = require('apollo-server');
const { resolvers, typeDefs } = require('./schema');

const validateToken = authToken => {
  // ... validate token and return a Promise, rejects in case of an error
};

const findUser = authToken => {
  return tokenValidationResult => {
    // ... finds user by auth token and return a Promise, rejects in case of an error
  };
};

const server = new ApolloServer({
  typeDefs,
  resolvers,
  subscriptions: {
    onConnect: (connectionParams, webSocket) => {
      if (connectionParams.authToken) {
        return validateToken(connectionParams.authToken)
          .then(findUser(connectionParams.authToken))
          .then(user => {
            return {
              currentUser: user,
            };
          });
      }

      throw new Error('Missing auth token!');
    },
  },
});

server.listen().then(({ url, subscriptionsUrl }) => {
  console.log(`🚀 Server ready at ${url}`);
  console.log(`🚀 Subscriptions ready at ${subscriptionsUrl}`);
});
```

The example above validates the user's token that is sent with the first initialization message on the transport, then it looks up the user and returns the user object as a Promise. The user object found will be available as `context.currentUser` in your GraphQL resolvers.

In case of an authentication error, the Promise will be rejected, which prevents the client's connection.


## Using with middleware integrations

You can use subscriptions with any of Apollo Server's supported [middleware integrations](../integrations/middleware/). To do so, you call `installSubscriptionHandlers` on your `ApolloServer` instance.

This example enables subscriptions for an Express server that uses `apollo-server-express`:

```js
const http = require('http');
const { ApolloServer } = require('apollo-server-express');
const express = require('express');

async function startApolloServer() {
  const PORT = 4000;
  const app = express();
  const server = new ApolloServer({ typeDefs, resolvers });
  await server.start();
  server.applyMiddleware({app})

  const httpServer = http.createServer(app);
  server.installSubscriptionHandlers(httpServer); // highlight-line

  // Make sure to call listen on httpServer, NOT on app.
  await new Promise(resolve => httpServer.listen(PORT, resolve));
  console.log(`🚀 Server ready at http://localhost:${PORT}${server.graphqlPath}`);
  console.log(`🚀 Subscriptions ready at ws://localhost:${PORT}${server.subscriptionsPath}`);
  return { server, app, httpServer };
}
```

## Production `PubSub` libraries

[As mentioned above](#the-pubsub-class), the `PubSub` class is _not_ recommended for production environments, because its event-publishing system is in-memory. This means that events published by _one_ instance of your GraphQL server are not received by subscriptions that are handled by _other_ instances.

Instead, you should use a subclass of the [`PubSubEngine` abstract class](https://github.com/apollographql/graphql-subscriptions/blob/master/src/pubsub-engine.ts) that you can back with an external datastore such as Redis or Kafka.

The following are community-created `PubSub` libraries for popular event-publishing systems:

- [Redis](https://github.com/davidyaha/graphql-redis-subscriptions)
- [Google PubSub](https://github.com/axelspringer/graphql-google-pubsub)
- [MQTT enabled broker](https://github.com/davidyaha/graphql-mqtt-subscriptions)
- [RabbitMQ](https://github.com/cdmbase/graphql-rabbitmq-subscriptions)
- [Kafka](https://github.com/ancashoria/graphql-kafka-subscriptions)
- [Postgres](https://github.com/GraphQLCollege/graphql-postgres-subscriptions)
- [Google Cloud Firestore](https://github.com/MrBoolean/graphql-firestore-subscriptions)
- [Ably Realtime](https://github.com/ably-labs/graphql-ably-pubsub)

If none of these libraries fits your use case, you can also create your own `PubSubEngine` subclass. If you create a new open-source library, click **Edit on GitHub** to let us know about it!
